using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Threading;

namespace GameOverlayWPF.Services
{
    /// <summary>
    /// 企业级动画服务 - 提供极致丝滑的缩放和透明度动画效果
    /// 优化性能，减少GPU负载，确保60FPS流畅体验
    /// 支持动态配置、性能监控、自适应优化
    /// </summary>
    public class AnimationService
    {
        private static AnimationService _instance;
        private static readonly object _lockObject = new object();
        
        // 性能监控
        private readonly PerformanceCounter _cpuCounter;
        private readonly Dictionary<FrameworkElement, Storyboard> _activeAnimations;
        private AnimationConfig _currentConfig;
        private readonly DispatcherTimer _performanceMonitorTimer;

        // 单例模式
        public static AnimationService Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_lockObject)
                    {
                        if (_instance == null)
                            _instance = new AnimationService();
                    }
                }
                return _instance;
            }
        }

        private AnimationService()
        {
            // 初始化性能监控
            _activeAnimations = new Dictionary<FrameworkElement, Storyboard>();
            _currentConfig = AnimationConfig.Balanced;
            
            try
            {
                _cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"性能计数器初始化失败: {ex.Message}");
            }

            // 设置动画优先级
            Timeline.DesiredFrameRateProperty.OverrideMetadata(
                typeof(Timeline), 
                new FrameworkPropertyMetadata { DefaultValue = 60 }
            );

            // 启动性能监控定时器
            _performanceMonitorTimer = new DispatcherTimer
            {
                Interval = TimeSpan.FromSeconds(2)
            };
            _performanceMonitorTimer.Tick += OnPerformanceMonitorTick;
            _performanceMonitorTimer.Start();
        }

        /// <summary>
        /// 设置动画配置
        /// </summary>
        /// <param name="config">动画配置</param>
        public void SetConfiguration(AnimationConfig config)
        {
            _currentConfig = config ?? AnimationConfig.Balanced;
        }

        /// <summary>
        /// 获取当前配置
        /// </summary>
        public AnimationConfig CurrentConfig => _currentConfig;

        private void OnPerformanceMonitorTick(object sender, EventArgs e)
        {
            try
            {
                if (_cpuCounter != null)
                {
                    var cpuUsage = _cpuCounter.NextValue() / 100.0;
                    var memoryUsage = GC.GetTotalMemory(false) / (1024.0 * 1024.0 * 1024.0); // GB
                    
                    // 动态优化配置
                    if (cpuUsage > 0.7 || _activeAnimations.Count > _currentConfig.MaxConcurrentAnimations)
                    {
                        _currentConfig = _currentConfig.OptimizeForPerformance(cpuUsage, memoryUsage);
                        Debug.WriteLine($"性能优化: CPU={cpuUsage:P1}, 活动动画={_activeAnimations.Count}");
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"性能监控异常: {ex.Message}");
            }
        }

        /// <summary>
        /// 显示窗口动画 - 由小到大的丝滑效果
        /// </summary>
        /// <param name="window">目标窗口</param>
        /// <param name="onCompleted">完成回调</param>
        /// <param name="customConfig">自定义配置（可选）</param>
        /// <returns>异步任务</returns>
        public async Task ShowWindowWithScaleAsync(Window window, Action onCompleted = null, AnimationConfig customConfig = null)
        {
            if (window == null) return;

            var config = customConfig ?? _currentConfig;

            await window.Dispatcher.InvokeAsync(() =>
            {
                // 停止现有动画
                StopAnimation(window);

                // 预设初始状态
                window.Opacity = config.OpacityFrom;
                window.Visibility = Visibility.Visible;
                
                // 确保窗口有RenderTransform
                EnsureScaleTransform(window);
                var scaleTransform = (ScaleTransform)window.RenderTransform;
                
                // 设置变换原点
                window.RenderTransformOrigin = new Point(config.TransformOriginX, config.TransformOriginY);
                
                // 初始状态
                scaleTransform.ScaleX = config.ScaleFrom;
                scaleTransform.ScaleY = config.ScaleFrom;

                // 创建高性能动画组
                var storyboard = new Storyboard();
                
                // 透明度动画
                var opacityAnimation = CreateOpacityAnimation(
                    config.OpacityFrom, 
                    config.OpacityTo, 
                    config.ShowDuration, 
                    config.ShowEasing, 
                    config);
                Storyboard.SetTarget(opacityAnimation, window);
                Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(UIElement.OpacityProperty));
                
                // X轴缩放动画
                var scaleXAnimation = CreateScaleAnimation(
                    config.ScaleFrom, 
                    config.ScaleTo, 
                    config.ShowDuration, 
                    config.ShowEasing, 
                    config);
                Storyboard.SetTarget(scaleXAnimation, scaleTransform);
                Storyboard.SetTargetProperty(scaleXAnimation, new PropertyPath(ScaleTransform.ScaleXProperty));
                
                // Y轴缩放动画
                var scaleYAnimation = CreateScaleAnimation(
                    config.ScaleFrom, 
                    config.ScaleTo, 
                    config.ShowDuration, 
                    config.ShowEasing, 
                    config);
                Storyboard.SetTarget(scaleYAnimation, scaleTransform);
                Storyboard.SetTargetProperty(scaleYAnimation, new PropertyPath(ScaleTransform.ScaleYProperty));

                storyboard.Children.Add(opacityAnimation);
                storyboard.Children.Add(scaleXAnimation);
                storyboard.Children.Add(scaleYAnimation);

                // 添加视觉效果
                if (config.EnableShadow)
                {
                    AddShadowEffect(window, storyboard, config, true);
                }

                if (config.EnableBlur && System.Environment.OSVersion.Version.Major >= 6)
                {
                    AddBlurEffect(window, storyboard, config, true);
                }
                
                // 注册活动动画
                _activeAnimations[window] = storyboard;
                
                // 完成事件处理
                storyboard.Completed += (s, e) =>
                {
                    _activeAnimations.Remove(window);
                    onCompleted?.Invoke();
                };
                
                // 启动动画 - 使用最高优先级确保流畅度
                storyboard.Begin();
                
            }, DispatcherPriority.Render);
        }

        /// <summary>
        /// 隐藏窗口动画 - 由大到小的丝滑效果
        /// </summary>
        /// <param name="window">目标窗口</param>
        /// <param name="onCompleted">完成回调</param>
        /// <param name="customConfig">自定义配置（可选）</param>
        /// <returns>异步任务</returns>
        public async Task HideWindowWithScaleAsync(Window window, Action onCompleted = null, AnimationConfig customConfig = null)
        {
            if (window == null) return;

            var config = customConfig ?? _currentConfig;

            await window.Dispatcher.InvokeAsync(() =>
            {
                // 停止现有动画
                StopAnimation(window);

                // 确保窗口有RenderTransform
                EnsureScaleTransform(window);
                var scaleTransform = (ScaleTransform)window.RenderTransform;
                
                // 创建隐藏动画组
                var storyboard = new Storyboard();
                
                // 透明度动画
                var opacityAnimation = CreateOpacityAnimation(
                    window.Opacity, 
                    config.OpacityFrom, 
                    config.HideDuration, 
                    config.HideEasing, 
                    config);
                Storyboard.SetTarget(opacityAnimation, window);
                Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(UIElement.OpacityProperty));
                
                // X轴缩放动画
                var scaleXAnimation = CreateScaleAnimation(
                    scaleTransform.ScaleX, 
                    config.ScaleHideTo, 
                    config.HideDuration, 
                    config.HideEasing, 
                    config);
                Storyboard.SetTarget(scaleXAnimation, scaleTransform);
                Storyboard.SetTargetProperty(scaleXAnimation, new PropertyPath(ScaleTransform.ScaleXProperty));
                
                // Y轴缩放动画
                var scaleYAnimation = CreateScaleAnimation(
                    scaleTransform.ScaleY, 
                    config.ScaleHideTo, 
                    config.HideDuration, 
                    config.HideEasing, 
                    config);
                Storyboard.SetTarget(scaleYAnimation, scaleTransform);
                Storyboard.SetTargetProperty(scaleYAnimation, new PropertyPath(ScaleTransform.ScaleYProperty));

                storyboard.Children.Add(opacityAnimation);
                storyboard.Children.Add(scaleXAnimation);
                storyboard.Children.Add(scaleYAnimation);

                // 添加视觉效果
                if (config.EnableShadow)
                {
                    AddShadowEffect(window, storyboard, config, false);
                }

                if (config.EnableBlur && System.Environment.OSVersion.Version.Major >= 6)
                {
                    AddBlurEffect(window, storyboard, config, false);
                }
                
                // 注册活动动画
                _activeAnimations[window] = storyboard;
                
                // 完成时隐藏窗口
                storyboard.Completed += (s, e) =>
                {
                    _activeAnimations.Remove(window);
                    window.Visibility = Visibility.Hidden;
                    onCompleted?.Invoke();
                };
                
                // 启动动画
                storyboard.Begin();
                
            }, DispatcherPriority.Render);
        }

        /// <summary>
        /// 为控件添加悬停缩放效果
        /// </summary>
        /// <param name="element">目标控件</param>
        /// <param name="hoverScale">悬停时的缩放比例</param>
        public void AddHoverScaleEffect(FrameworkElement element, double hoverScale = 1.05)
        {
            if (element == null) return;

            EnsureScaleTransform(element);
            element.RenderTransformOrigin = new Point(0.5, 0.5);

            element.MouseEnter += (s, e) =>
            {
                var scaleTransform = (ScaleTransform)element.RenderTransform;
                AnimateScale(scaleTransform, scaleTransform.ScaleX, hoverScale, 150, _currentConfig.ShowEasing);
            };

            element.MouseLeave += (s, e) =>
            {
                var scaleTransform = (ScaleTransform)element.RenderTransform;
                AnimateScale(scaleTransform, scaleTransform.ScaleX, 1.0, 150, _currentConfig.HideEasing);
            };
        }

        /// <summary>
        /// 脉冲动画效果 - 适用于提醒通知
        /// </summary>
        /// <param name="element">目标控件</param>
        /// <param name="pulseScale">脉冲缩放比例</param>
        /// <param name="duration">动画时长</param>
        public void PulseElement(FrameworkElement element, double pulseScale = 1.1, int duration = 600)
        {
            if (element == null) return;

            EnsureScaleTransform(element);
            element.RenderTransformOrigin = new Point(0.5, 0.5);
            var scaleTransform = (ScaleTransform)element.RenderTransform;

            var storyboard = new Storyboard();
            var easing = new SineEase { EasingMode = EasingMode.EaseInOut };

            // 缩放到最大然后恢复
            var scaleXAnimation1 = CreateScaleAnimation(1.0, pulseScale, duration / 2, easing, _currentConfig);
            var scaleYAnimation1 = CreateScaleAnimation(1.0, pulseScale, duration / 2, easing, _currentConfig);
            
            var scaleXAnimation2 = CreateScaleAnimation(pulseScale, 1.0, duration / 2, easing, _currentConfig);
            scaleXAnimation2.BeginTime = TimeSpan.FromMilliseconds(duration / 2);
            var scaleYAnimation2 = CreateScaleAnimation(pulseScale, 1.0, duration / 2, easing, _currentConfig);
            scaleYAnimation2.BeginTime = TimeSpan.FromMilliseconds(duration / 2);

            Storyboard.SetTarget(scaleXAnimation1, scaleTransform);
            Storyboard.SetTargetProperty(scaleXAnimation1, new PropertyPath(ScaleTransform.ScaleXProperty));
            Storyboard.SetTarget(scaleYAnimation1, scaleTransform);
            Storyboard.SetTargetProperty(scaleYAnimation1, new PropertyPath(ScaleTransform.ScaleYProperty));
            
            Storyboard.SetTarget(scaleXAnimation2, scaleTransform);
            Storyboard.SetTargetProperty(scaleXAnimation2, new PropertyPath(ScaleTransform.ScaleXProperty));
            Storyboard.SetTarget(scaleYAnimation2, scaleTransform);
            Storyboard.SetTargetProperty(scaleYAnimation2, new PropertyPath(ScaleTransform.ScaleYProperty));

            storyboard.Children.Add(scaleXAnimation1);
            storyboard.Children.Add(scaleYAnimation1);
            storyboard.Children.Add(scaleXAnimation2);
            storyboard.Children.Add(scaleYAnimation2);

            storyboard.Begin();
        }

        #region 私有辅助方法

        private void StopAnimation(FrameworkElement element)
        {
            if (_activeAnimations.TryGetValue(element, out var storyboard))
            {
                storyboard.Stop();
                _activeAnimations.Remove(element);
                
                // 重要：重置 ScaleTransform 到原始状态，防止界面变小
                if (element.RenderTransform is ScaleTransform scaleTransform)
                {
                    scaleTransform.ScaleX = 1.0;
                    scaleTransform.ScaleY = 1.0;
                }
            }
        }

        private void EnsureScaleTransform(FrameworkElement element)
        {
            if (element.RenderTransform == null || !(element.RenderTransform is ScaleTransform))
            {
                element.RenderTransform = new ScaleTransform(1.0, 1.0);
            }
        }

        private DoubleAnimation CreateOpacityAnimation(double from, double to, int duration, IEasingFunction easing, AnimationConfig config)
        {
            var animation = new DoubleAnimation(from, to, TimeSpan.FromMilliseconds(duration))
            {
                EasingFunction = easing,
                AccelerationRatio = config.AccelerationRatio,
                DecelerationRatio = config.DecelerationRatio
            };
            
            // 启用硬件加速
            if (config.EnableHardwareAcceleration)
            {
                Timeline.SetDesiredFrameRate(animation, config.FrameRate);
                RenderOptions.SetBitmapScalingMode(animation, BitmapScalingMode.HighQuality);
            }
            
            return animation;
        }

        private DoubleAnimation CreateScaleAnimation(double from, double to, int duration, IEasingFunction easing, AnimationConfig config)
        {
            var animation = new DoubleAnimation(from, to, TimeSpan.FromMilliseconds(duration))
            {
                EasingFunction = easing,
                AccelerationRatio = config.AccelerationRatio,
                DecelerationRatio = config.DecelerationRatio
            };
            
            // 启用硬件加速
            if (config.EnableHardwareAcceleration)
            {
                Timeline.SetDesiredFrameRate(animation, config.FrameRate);
                RenderOptions.SetBitmapScalingMode(animation, BitmapScalingMode.HighQuality);
            }
            
            return animation;
        }

        private void AnimateScale(ScaleTransform transform, double from, double to, int duration, IEasingFunction easing)
        {
            var animationX = CreateScaleAnimation(from, to, duration, easing, _currentConfig);
            var animationY = CreateScaleAnimation(from, to, duration, easing, _currentConfig);
            
            transform.BeginAnimation(ScaleTransform.ScaleXProperty, animationX);
            transform.BeginAnimation(ScaleTransform.ScaleYProperty, animationY);
        }

        private void AddShadowEffect(FrameworkElement element, Storyboard storyboard, AnimationConfig config, bool isShow)
        {
            if (element.Effect == null || !(element.Effect is DropShadowEffect))
            {
                element.Effect = new DropShadowEffect
                {
                    BlurRadius = 0,
                    ShadowDepth = config.ShadowDepth,
                    Opacity = 0,
                    Color = Colors.Black,
                    Direction = 315
                };
            }

            var effect = (DropShadowEffect)element.Effect;
            var targetOpacity = isShow ? config.ShadowOpacity : 0;
            var duration = isShow ? config.ShowDuration : config.HideDuration;

            var shadowAnimation = new DoubleAnimation(effect.Opacity, targetOpacity, TimeSpan.FromMilliseconds(duration))
            {
                EasingFunction = isShow ? config.ShowEasing : config.HideEasing
            };

            Storyboard.SetTarget(shadowAnimation, effect);
            Storyboard.SetTargetProperty(shadowAnimation, new PropertyPath(DropShadowEffect.OpacityProperty));
            storyboard.Children.Add(shadowAnimation);
        }

        private void AddBlurEffect(FrameworkElement element, Storyboard storyboard, AnimationConfig config, bool isShow)
        {
            if (element.Effect == null || !(element.Effect is BlurEffect))
            {
                element.Effect = new BlurEffect
                {
                    Radius = 0
                };
            }

            var effect = (BlurEffect)element.Effect;
            var targetRadius = isShow ? config.BlurRadius : 0;
            var duration = isShow ? config.ShowDuration : config.HideDuration;

            var blurAnimation = new DoubleAnimation(effect.Radius, targetRadius, TimeSpan.FromMilliseconds(duration))
            {
                EasingFunction = isShow ? config.ShowEasing : config.HideEasing
            };

            Storyboard.SetTarget(blurAnimation, effect);
            Storyboard.SetTargetProperty(blurAnimation, new PropertyPath(BlurEffect.RadiusProperty));
            storyboard.Children.Add(blurAnimation);
        }

        #endregion

        /// <summary>
        /// 清理资源
        /// </summary>
        public void Dispose()
        {
            // 清理可能的资源
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }
}
